iT邦幫忙

2022 iThome 鐵人賽

DAY 8
1

前面兩天有提到 FacadeAdapter 兩種設計模式,裡面的範例程式碼內容基本上是環繞在三個物件導向中的基礎概念:物件、封裝、抽象類別。今天的主要目的就是希望從理解設計模式的角度出發,用全新的方式來看待物件導向設計。

以下是本篇主要的內容:

  • 比較傳統上對物件的看法(將物件視為資料和方法的簡單集合) 與新的看法(將物件視為具有責任的東西) 的異同;
  • 比較傳統上對封裝的看法(將封裝視為資料的隱藏) 與新的看法(將封装視為隱藏一切的一種能力) 的異同。尤其重要的是看到封裝可以用來包含行為中的變化;
  • 比較對行為變化的不同處理方式的異同;
  • 比較傳統的使用繼承的方式(用於特殊化和再利用) 與新的方式(作為物件分類的一種方法) 的異同。新的觀點考慮到了包含物件的行為變化;

物件:傳統看法與新看法

傳統上物件被視為具有方法的資料,也就是一個包含著一些欄位、屬性以及方法的類別(我原本也就這麼認為XD),但如果回想一下 DAY3 討論範型時提到,我們將如何到下一堂上課教室的責任,從老師身上轉移到學生本身,最大的重點就是『責任』。

從概念視角出發 — 物件是具有責任的一個實體,這些責任定義了物件的行為,還能夠將物件視為具有特定行為的實體。

回顧一下:

public class Program
{
    static void Main(string[] args)
    {
        // 我們給學生一個「去下一間教室」的規定,學生使用自己的方式到下一間教室
        Student student = new Student();
        student.goNextClassRoom();
    }
}

public class Student : IStudentRule
{
    // 介面有定義的屬性與方法名稱一定要實作
    public string transportationType { get; set; }
    public void goNextClassRoom()
    {
        transportationType = "腳踏車";
        Console.WriteLine($"我使用{transportationType}到下一間教室");
    }
}

public interface IStudentRule
{
    // 介面定義好需要的屬性與方法名稱
    string transportationType { get; set; }
    void goNextClassRoom();
}

我們透過 IStudentRule(規範) 讓學生去繼承,因此學生們知道他們要做什麼,並且需要為此負責,實作的部分就交給學生自己去處理,我們不用知道,只需要去注意定義好的介面是不是學生真的要去負責的東西,因此,真正需要去關注的是「動機」而非實作。

封裝:傳統看法與新看法

在傳統看法中封裝就是看成「資料隱藏」,但封裝其實應該被視為「任何形式的隱藏」,可以如下:

  • 實作細節;
  • 衍生類別;
  • 設計細節;
  • 實體化規則;

讓我們用UML來看看

下圖是在 DAY7 的 Adapter 範例模型

https://ithelp.ithome.com.tw/upload/images/20220918/20136443AJQ0HPjne0.png

我們將他稍微小改一下

現在電腦裡所有的外接口我讓他們都繼承自 Output 這個介面,而螢幕直接使用這個介面就好,他再也不用管要用哪個接口,如果今天螢幕的外接頭換成了AVG,一樣也是對到 Output 即可。

https://ithelp.ithome.com.tw/upload/images/20220919/20136443GCHuoDSPFL.png

在這張改過的UML圖裡,可以分成很多種層次的封裝:

  • 資料的封裝 — DisplayPortUSBHDMI物件中的資料對其他所有物件來說都是隱藏的。
  • 方法的封裝 — 意即每個物件的 Connect() 方法,實作的細節都不同,也互相看不到。
  • 其他物件的封裝 — 除了 HDMI 之外,其他物件對 TypecToHdmiAdapter 物件是一無所知的。
  • 類型的封裝 — Screen 看不到 DisplayPortUSBHDMI物件,他只知道 Output

魔鬼藏在細節裡

如果仔細看會發現, TypecToHdmiAdapter 這個物件實際上是一個『特殊化類別』,也就是為了做到某些特殊的事情而產生的。假設今天我變成是 AVG 的外接口想要去轉成 HDMI,那是不是就要再多一個 AvgToHdmiAdapter 的類別出來並且一樣去繼承 HDMI,這就是特殊化物件會帶來的問題:

  • 可能導致弱內聚
  • 減少再利用的可能性
  • 無法根據變化良好伸縮

至於如何去解決這個問題,大家可以來思考一下,明天會來解答!


上一篇
【DAY7】Adapter模式 - 外接螢幕的故事
下一篇
【DAY9】Strategy模式 - 強化我的轉接器
系列文
勇闖秘境!探索物件導向背後的設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言